package com.yh.redisTest.common;

/**
 * Created by crj on 2017/11/16.
 */
import java.io.Serializable;
import java.util.concurrent.TimeUnit;


import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.stereotype.Component;


/**
 * 创建时间：2016年12月8日 下午5:44:16
 *
 * redis分布式锁
 *
 * @author andy
 * @version 2.2
 */
@Component
  public class RedisDistributionLock {

    private static final long LOCK_TIMEOUT = 5*60 * 1000; //加锁超时时间 单位毫秒  意味着加锁期间内执行完操作 如果未完成会有并发现象

    private static final Log LOG = LogFactory.getLog(RedisDistributionLock.class); //redis锁日志


    private static RedisTemplate<Serializable, Serializable> redisTemplate = null;
    /**
     * 取到锁加锁 取不到锁一直等待直到获得锁
     */
    public RedisDistributionLock(RedisTemplate<Serializable, Serializable> redisTemplate){
        this.redisTemplate=redisTemplate;
    }
    public Long lock(String lockKey, String threadname) {
            Long lock_timeout = System.currentTimeMillis() + LOCK_TIMEOUT + 1; //锁时间
            if (redisTemplate.execute(new RedisCallback<Boolean>() {
                @Override
                public Boolean doInRedis(RedisConnection connection) throws DataAccessException {
                    JdkSerializationRedisSerializer jdkSerializer = new JdkSerializationRedisSerializer();
                    byte[] value = lock_timeout.toString().getBytes();
                    return connection.setNX(lockKey.getBytes(), value);
                }
            })) { //如果加锁成功
             //   LOG.info(threadname + "加锁成功++++++++111111111");
                redisTemplate.expire(lockKey, LOCK_TIMEOUT, TimeUnit.MILLISECONDS); //设置超时时间，释放内存
                return lock_timeout;
            }
            return null;
    }


    public void unlock(String lockKey, long lockvalue, String threadname) {
      //  LOG.info(threadname + "执行解锁==========" + redisTemplate.opsForValue().get(lockKey));//正常直接删除 如果异常关闭判断加锁会判断过期时间
        Long currt_lock_timeout_Str =  Long.valueOf((String) redisTemplate.opsForValue().get(lockKey)); // redis里的时间

        if (currt_lock_timeout_Str != null && currt_lock_timeout_Str == lockvalue) {//如果是加锁者 则删除锁 如果不是则等待自动过期 重新竞争加锁
            redisTemplate.delete(lockKey); //删除键
            LOG.info(threadname + "解锁成功-----------------");
        }
    }

}